' The ExtentionType property must return the type of the SoapExtension class.
Public Overrides ReadOnly Property ExtensionType() As System.Type
Get
Return GetType(SoapCustomAuthentication)
End Get
End Property
' The RequiredSubscriptionLevel property is a custom property for this attribute.
Dim m_RequiredSubscriptionLevel As Integer
Property RequiredSubscriptionLevel() As Integer
Get
Return m_RequiredSubscriptionLevel
End Get
Set(ByVal Value As Integer)
m_RequiredSubscriptionLevel = Value
End Set
End Property
End Class
' The Soap extension class.
Class SoapCustomAuthentication
Inherits SoapExtension
' When the SoapExtension class is instantiated, the GetInitializer method is called.
' This method receives a reference to the custom attribute that flagged the method.
' The value returned by GetInitializer is then passed to the Initialize method each
' This overloads of the GetInitializer method is called if the Soap extension is
' installed in web.config and receives the Type of the WebService class.
Public Overloads Overrides Function GetInitializer(ByVal serviceType As System.Type) As Object
' In this case we just return 1 - the lowest subscription level necessary to
' access methods in the Web Service
If serviceType Is GetType(SoapCustomAuthentication) Then
Return 1
End If
End Function
' This overloads of the GetInitializer method is called if the Soap extension is
' installed because a method was flagged with a SoapExtensionAttribute
' and receives the attribute in the second argument.
Public Overloads Overrides Function GetInitializer(ByVal methodInfo As System.Web.Services.Protocols.LogicalMethodInfo, ByVal attribute As System.Web.Services.Protocols.SoapExtensionAttribute) As Object
' Get a reference to the attribute.
Dim scaAttr As SoapCustomAuthenticationAttribute = DirectCast(attribute, SoapCustomAuthenticationAttribute)
' Return its RequiredSubscriptionLevel property.
Return scaAttr.RequiredSubscriptionLevel
End Function
' The Initialize method is called with the RequiredSubscriptionLevel integer
' in its argument.
Dim RequiredSubscriptionLevel As Integer
Public Overrides Sub Initialize(ByVal initializer As Object)
' Save the required subscription level for later.
RequiredSubscriptionLevel = CInt(initializer)
End Sub
Dim oldStream As Stream
Dim newStream As Stream
' The ChainStream is called when the SoapExtension class is instantiated.
Public Overrides Function ChainStream(ByVal stream As Stream) As Stream
' Save the old stream.
oldStream = stream
' Create a new stream and return it.
newStream = New MemoryStream()
Return newStream
End Function
' a reusable routine used by most SOAP extensions
Private Sub CopyStream(ByVal source As Stream, ByVal dest As Stream, Optional ByVal resetSource As Boolean = True)
Dim sr As New StreamReader(source)
Dim sw As New StreamWriter(dest)
sw.WriteLine(sr.ReadToEnd)
sw.Flush()
End Sub
' This method is called multiple times for each message.
Public Overrides Sub ProcessMessage(ByVal message As System.Web.Services.Protocols.SoapMessage)
Select Case message.Stage
Case SoapMessageStage.BeforeDeserialize
CopyStream(oldStream, newStream)
newStream.Position = 0
Case SoapMessageStage.AfterDeserialize
' The message has been deserialized, so we can access the headers collection.
If EvalSubscriptionLevel(message) < RequiredSubscriptionLevel Then
' Throw an exception if subscription level isn't adequate.
Throw New SoapException("Invalid account or insufficient subscription level", SoapException.ClientFaultCode)
End If
Case SoapMessageStage.BeforeSerialize
Case SoapMessageStage.AfterSerialize
newStream.Position = 0
CopyStream(newStream, oldStream)
End Select
End Sub
Private Function EvalSubscriptionLevel(ByVal message As SoapMessage) As Integer
' Check whether there is a header of type AccountInfoHeader
Dim header As SoapHeader
For Each header In message.Headers
If TypeOf header Is AccountInfoHeader Then
' cast to the propert type
Dim accountInfo As AccountInfoHeader = DirectCast(header, AccountInfoHeader)
' Check user credentials and return subscription level.